﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CloudPms.Common.CacheInterface;
using CloudPms.Common.CacheProvider;
using CloudPms.Common.Log;
using CloudPms.Common.Utils;
using CloudPms.Domain.Interface;
using CloudPms.Domain.Repository;
using CloudPms.Entity.Entities;
using Microsoft.Practices.Unity;

namespace CloudPms.Logic.Business
{
    /// <summary>
    /// 房间信息缓存存储与更新服务
    /// <para>--------------------------</para>
    /// <para>@Author: cnalexi@gmail.com</para> 
    /// <para>@Create: 2012/10/06</para>  
    /// <example>
    /// <code>
    /// var roomCache = RoomStatusCache.Instance;
    /// </code>
    /// </example> 
    /// </summary>
    public class RoomStatusCache
    {
        private static volatile RoomStatusCache _instance;
        private static readonly object lockThis = new object();
        private readonly IUnityContainer container = UnityContainerService.GetContainer();

        private readonly DateTime InitTimeStamp = DateTime.Parse("1984/11/09 18:00:00 PM");

        /// <summary>
        /// 版本队列,string：hotelId, Datetime:更新版本时间
        /// </summary>
        private IDictionary<string, DateTime> _versionQueue = new Dictionary<string, DateTime>();
        
        private RoomStatusCache()
        {
        }

        public static RoomStatusCache Instance
        {
            get
            {
                if (_instance == null)
                {
                    lock (lockThis)
                    {
                        if (_instance == null)
                        {
                            _instance = new RoomStatusCache();
                        }
                    }
                }
                return _instance;
            }
        }

        /// <summary>
        /// 初始化房态缓存
        /// </summary>
        public void Initialization()
        {
            var roomRepository = container.Resolve<IRoomRepository>();

            var rcs = container.Resolve<IRoomCacheStore>();

            var hotelConns = HotelBizDayCache.Instance.GetHotelConnection().Keys;

            Parallel.ForEach(hotelConns, hotelId =>
                {
                    try
                    {
                        var rooms = roomRepository.BatchGet(hotelId, r => r.HotelID == hotelId && r.IsValid == true);

                        rcs.BatchSet(hotelId, rooms);
                    }catch(Exception ex)
                    {
                        OperateLog.ErrorLog("初始化房态载入缓存失败，请检查数据库连接和缓存服务器状态",ex);
                    }
                });
        }

        public IList<Room> GetCacheRooms(string hotelId,DateTime timestamp)
        {
            if (string.IsNullOrWhiteSpace(hotelId) || timestamp < InitTimeStamp)
            {
                throw new ArgumentNullException("酒店编号不能为空或者获取房态时间戳不能小于默认时间1984年");
            }

            var rcs = container.Resolve<IRoomCacheStore>();

            var rooms = rcs.BatchGet(hotelId, timestamp);

            return rooms;
        }

        public IList<Room> GetCacheRooms(string hotelId)
        {
            var rcs = container.Resolve<IRoomCacheStore>();

            var rooms = rcs.BatchGet(hotelId);

            return rooms;
        }

        public IList<RoomZip> SerializeRooms(IList<Room> rooms)
        {
            if(rooms==null||!rooms.Any())return null;

            IList<RoomZip> roomZips = new List<RoomZip>();

            var orderIds = rooms.Where(r=>!string.IsNullOrWhiteSpace(r.OrderID)).Select(r => r.OrderID);

            IList<Order> orders = new List<Order>();

            if (orderIds.Any())
            {
                //orders=获取缓存中的ORDER
            }

            Parallel.ForEach(rooms, r =>
                {
                    Order order = null;
                    if(!string.IsNullOrWhiteSpace(r.OrderID))
                    {
                        order = orders.FirstOrDefault(o => o.OrderID == r.OrderID);
                    }
                    roomZips.Add(BuildRoomZip(r, order));
                });

            return roomZips;
        }

        public object[] GetRoomZips(string hotelId, DateTime? timestamp)
        {
            var rcs = container.Resolve<IRoomCacheStore>();

            IList<Room> rooms = timestamp.HasValue 
                              ? rcs.BatchGet(hotelId, timestamp.Value) 
                              : rcs.BatchGet(hotelId);

            if (rooms == null || !rooms.Any())return null;

            long cacheTime = rooms.Max(r => r.ModifiedTime).Ticks;

            IList<RoomZip> roomZips = SerializeRooms(rooms);

            return new object[]
                {
                    cacheTime,
                    roomZips
                };
        }

        public DateTime GetTimestamp(string hotelId)
        {
            var rcs = container.Resolve<IRoomCacheStore>();
            return rcs.GetCacheTime(hotelId);
        }

        private RoomZip BuildRoomZip(Room room, Order order)
        {
            var roomZip = new RoomZip
                {
                    Bu=room.BuildingID,
                    Fl=room.FloorID,
                    Iv=room.IsValid,
                    No=room.RoomNo,
                    Rd=room.Description,
                    Rt=room.RoomTypeID,
                    St=room.Status,
                    Rn=room.RoomName,
                    Lr=room.LockRepairEmployee,
                    Mo=room.Memo,
                };

            if (order != null&&order.IsValid)
            {
                roomZip.Od = order.OrderID;
                roomZip.Ra = BuildRoomAttribute(order);
            }
            return roomZip;
        }

        private string BuildRoomAttribute(Order order)
        {
            //TODO: 获取营业日
            DateTime bizDay = DateTime.Today;

            IList<string> attrs = new List<string>();
            if (!string.IsNullOrWhiteSpace(order.RelateGroupID))
            {
                attrs.Add(EnumHelper.GetCode(RoomAttribute.GC));
            }
            if (order.CheckInType == EnumHelper.GetCode(CheckInType.HR))
            {
                attrs.Add((DateTime.Now - order.EndDate).Minutes > -15
                              ? EnumHelper.GetCode(RoomAttribute.PR)
                              : EnumHelper.GetCode(RoomAttribute.PO));
            }
            if (order.CheckInType == EnumHelper.GetCode(CheckInType.DR))
            {
                attrs.Add((DateTime.Now - order.EndDate).Minutes > -15
                              ? EnumHelper.GetCode(RoomAttribute.DR)
                              : EnumHelper.GetCode(RoomAttribute.DO));
            }
            if (order.EndDate.Date == bizDay)
            {
                attrs.Add(EnumHelper.GetCode(RoomAttribute.WO));
            }
            if (order.IsQuickLeave)
            {
                attrs.Add(EnumHelper.GetCode(RoomAttribute.QD));
            }
            if (string.IsNullOrWhiteSpace(order.Memo))
            {
                attrs.Add(EnumHelper.GetCode(RoomAttribute.MG));
            }
            if (order.IsVIP)
            {
                attrs.Add(EnumHelper.GetCode(RoomAttribute.VP));
            }

            string attrStr = string.Empty;

            if (attrs.Any())attrStr= string.Join(" ", attrs);

            return attrStr;
        }

    }
}
